#!/usr/bin/perl
use strict;

BEGIN {
    eval { require Gantry::Server; };
    if ( $@ ) {
        my $msg = "\n  You need to install Gantry, rerun Bigtop's Build.PL,\n"
                . "  and reinstall Bigtop before using tentmaker.\n\n";

        die $msg;
    }
}

use File::Spec;
use Getopt::Long;
use Gantry::Server;
use IO::Prompt;

use Bigtop::TentMaker qw{ -Engine=CGI -TemplateEngine=TT };
use Bigtop::TentMakerPath;
use Bigtop::ScriptHelp::Style;

$SIG{ INT } = \&trap_int;

my $port = 8080;
my $new_app_name;
my $add_bigtop_file;
my $style;

GetOptions(
    'port|p=s'  => \$port,
    'new|n=s'   => \$new_app_name,
    'add|a=s'   => \$add_bigtop_file,
    'style|s=s' => \$style,
    'help|h'    => \&help,
);

my $action_flags = 0;
$action_flags++ if $new_app_name;
$action_flags++ if $add_bigtop_file;

if ( $action_flags > 1 ) {
    die "--new and --add are incompatible\n";
}

if ( $new_app_name and not Bigtop::ScriptHelp::valid_ident( $new_app_name ) ) {
    die "--new requires valid package name, '$new_app_name' is invalid.\n";
}

if ( $add_bigtop_file and not -f $add_bigtop_file ) {
    die "--add requires valid input file,\n"
        .   "   couldn't read '$add_bigtop_file': $!\n";
}

# You could do this with a Damianism:
#my $file = ( $new_app_name )    ? ''
#         : ( $add_bigtop_file ) ? $add_bigtop_file
#         :                        shift || '';
           
# set the file name
my $file;

if    ( $new_app_name    ) { $file = '';               }
elsif ( $add_bigtop_file ) { $file = $add_bigtop_file; }
else                       { $file = shift || '';      } 

my $template_path = File::Spec->catfile(
        Bigtop::TentMakerPath->get_template_path(), 'tenttemplates'
);

my $cgi = Gantry::Engine::CGI->new(
    {
        config => {
            root         => $template_path,
            file         => $file,
        },
        locations => {
            '/', 'Bigtop::TentMaker'
        }
    }
);

my $server = Gantry::Server->new( $port );
$server->set_engine_object( $cgi );

my $space     = ' ';
my $ascii_art = join $space, @ARGV;
$ascii_art    =~ s/^\s+//;
$ascii_art    =~ s/\s+$//;

my $script_help_style = Bigtop::ScriptHelp::Style->get_style( $style );

eval {
    Bigtop::TentMaker->take_performance_hit(
            $script_help_style, $file, $ascii_art, $new_app_name
    );
};
if ( $@ and $file =~ /^\d+$/ ) {
    die "usage: tentmaker [--port 8089] [options] [file]\n";
}
elsif ( $@ ) {
    die "$@\n";
}

$server->run();

sub trap_int {

    # see if there are changes
    exit unless Bigtop::TentMaker->dirty();

    @ARGV = (); # IO::Prompt uses @ARGV, don't let it

    my $response = '';
    my $prompt   = "\n\nYou hit CTRL-C, would you like to save changes? ";

    while ( length $response == 0 ) {
        $response = prompt $prompt;
        $response =~ s/\W+|\s+//gms;
        $response =~ s/A//;
        $prompt   = "\nPlease answer yes or no. ";
    }

    if ( $response =~ /^y/i ) {
        my $file = Bigtop::TentMaker->get_file() || 'tmp.bigtop';

        open my $OUTPUT, '>', $file or die "I couldn't write the changes\n";
        print $OUTPUT Bigtop::TentMaker->deparsed();
        close $OUTPUT;

        print STDERR "Saved $file\n";
    }
    exit;
}

sub help {
    print <<"EO_HELP";
    If you already have a bigtop file and don't need new tables:
        tentmaker filename.bigtop

    If you already have a bigtop file but need new tables:
        tentmaker -a filename.bigtop 'new_table->old_table'

    If you are starting from scratch:
        tentmaker -n AppName [ 'table_list->including_relationships' ]

    If you don't want port 8080:
    add -p your_port_number to any of the above (for example):
        tentmaker -p 8192 filename.bigtop
EO_HELP
    exit;
}

=head1 NAME

tentmaker - browser based bigtop file editor

=head1 USAGE

    tentmaker [ --port=8192 ] [ file ]

Or, to name a new app with optional table layout:

    tentmaker --new AppName style_info

Or, to augment an existing bigtop file:

    tentmaker --add file.bigtop style_info

See L</STYLES> below for what style_info can be.

=head1 DESCRIPTION

This script is a simple web server.  Tell it what file you want to
edit (or start from scratch) and an optional port (defaults to 8080).
Point your browser to that port and edit away.

=head1 OPTIONS

=over 4

=item --port (or -p)

Specifies a port for the server.  Defaults to 8080.

=item --new (or -n)

Allows you to specify the name of the app and optionally its table
relationships.  Requires a name for the app.  The rest of the command
line arguments are depend on what style you use, see L</STYLES>.

Normally this flag uses the default bigtop file from L<Bigtop::ScriptHelp>.
For your convenience, you can see it in examples/default.bigtop.  To
override it, copy that file to bigtopdef in the directory where you
invoke tentmaker -n, or to .bigtopdef in your home directory.
Edit the file to your heart's content.

The result must be a valid bigtop file, with one exception.  The file
you create will be used as a template toolkit template.  But, only three
things are available for subsitution:

=over 4

=item app_name

The name of the app from the command line.

=item no_colon_name

The app name, where all ::'s are replaced with underscores.

=item short_name

Everything after the last :: in the app_name in lower case.

=back

For example see examples/def.bigtop.tt.

=item --add (or -a)

Allows you to augment an existing bigtop file prior to editing it.
Requires a bigtop file name.  The rest of the command line arguments
as the same as for -n, see L</STYLES>.

=item --style (or -s)

Defaults to Original.  Specifies which Bigtop::ScriptHelp::Style:: module
will handle extra command line arguements and standard input.  See your
Style module's docs for details.

=back

=head1 STYLES

Any command line arguments not consumed by the options above are passed
to your style backend.  If you don't use -s, the Original style
is used.  If you do use -s, whatever style you choose is used.
All styles live in the Bigtop::ScriptHelp::Style:: namespace.
See their individual docs for what they know how to do.

This section used to be called "ASCII ART," the code which supported
that got factored out and became the default style
C<Bigtop::ScriptHelp::Style::Original>.  See it for details on
ASCII art.

=head1 AUTHOR

Phil Crow <crow.phil@gmail.com>

=head1 COPYRIGHT and LICENSE

Copyright (C) 2006 by Phil Crow

This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself, either Perl version 5.8.6 or,
at your option, any later version of Perl 5 you may have available.

=cut
